Fix SVM guest pin timer migration logic.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 28 Feb 2006 09:13:26 +0000 (10:13 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 28 Feb 2006 09:13:26 +0000 (10:13 +0100)
Signed-off-by: Tom Woller <thomas.woller@amd.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/include/asm-x86/hvm/svm/svm.h
xen/include/asm-x86/hvm/svm/vmcb.h

index 45dcaf28a1fbc9eb7969706259c07706fb2b30ae..568568d8e4a749282593fd5bfd91c11479ef6276 100644 (file)
@@ -820,8 +820,29 @@ void svm_relinquish_resources(struct vcpu *v)
 
 void arch_svm_do_resume(struct vcpu *v) 
 {
-    svm_do_resume(v);
-    reset_stack_and_jump(svm_asm_do_resume);
+    /* pinning VCPU to a different core? */
+    if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
+        svm_do_resume( v );
+        reset_stack_and_jump( svm_asm_do_resume );
+    }
+    else {
+        printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() );
+        v->arch.hvm_svm.launch_core = smp_processor_id();
+        svm_migrate_timers( v );
+        svm_do_resume( v );
+        reset_stack_and_jump( svm_asm_do_resume );
+    }
+}
+
+
+void svm_migrate_timers(struct vcpu *v)
+{
+    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+    migrate_timer( &vpit->pit_timer, v->processor );
+    migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
+    if ( hvm_apic_support(v->domain) && VLAPIC( v ))
+        migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
 }
 
 
@@ -2668,26 +2689,23 @@ asmlinkage void svm_asid(void)
 {
     struct vcpu *v = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    int core = smp_processor_id();
-    int oldcore = v->arch.hvm_svm.core; 
-    /* 
-     * if need to assign new asid or if switching cores, 
-     * then retire asid for old core, and assign new for new core.
-     */
-    if( v->arch.hvm_svm.core != core ) {
-        if (svm_dbg_on)
-            printk("old core %d new core %d\n",(int)v->arch.hvm_svm.core,(int)core);
-        v->arch.hvm_svm.core = core;
-    }
-    if( test_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags) ||
-          (oldcore != core)) {
-        if(!asidpool_assign_next(vmcb, 1, 
-                   oldcore, core)) {
+
+   /*
+    * if need to assign new asid, or if switching cores,
+    * retire asid for the old core, and assign a new asid to the current core.
+    */
+    if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) ||
+       ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) {
+        /* recycle asid */
+        if ( !asidpool_assign_next( vmcb, 1,
+            v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) {
             /* If we get here, we have a major problem */
             domain_crash_synchronous();
         }
+
+        v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
+        clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
     }
-    clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
 }
 
 /*
index 0fa4040e90f30d9808cca9a9be84c3722c5457dc..f67fb9aafbaf55528e9b6470fc743e586f2c81f3 100644 (file)
@@ -306,7 +306,7 @@ void destroy_vmcb(struct arch_svm_struct *arch_svm)
 {
     if(arch_svm->vmcb != NULL)
     {
-        asidpool_retire(arch_svm->vmcb, arch_svm->core);
+        asidpool_retire(arch_svm->vmcb, arch_svm->asid_core);
          free_vmcb(arch_svm->vmcb);
     }
     if(arch_svm->iopm != NULL) {
@@ -404,18 +404,17 @@ err_out:
 
 void svm_do_launch(struct vcpu *v)
 {
-    /* Update CR3, GDT, LDT, TR */
-    struct vmcb_struct *vmcb;
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     int core = smp_processor_id();
-    vmcb = v->arch.hvm_svm.vmcb;
     ASSERT(vmcb);
 
+    /* Update CR3, GDT, LDT, TR */
     svm_stts(v);
 
-    /* current core is the one we will perform the vmrun on */
-    v->arch.hvm_svm.core = core;
+    /* current core is the one we intend to perform the VMRUN on */
+    v->arch.hvm_svm.launch_core = v->arch.hvm_svm.asid_core = core;
     clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
-    if ( !asidpool_assign_next(vmcb, 0, core, core) )
+    if ( !asidpool_assign_next( vmcb, 0, core, core ))
         BUG();
 
     if (v->vcpu_id == 0)
index 097fd2da1a687aa2ad28ec85901a74c1fea10a9d..c6c848ec9034b1383de0043ea57aa28f69db9041 100644 (file)
@@ -54,6 +54,8 @@ extern int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa);
 /* For debugging. Remove when no longer needed. */
 extern void svm_dump_host_regs(const char *from);
 
+extern void svm_migrate_timers(struct vcpu *v);
+
 /* ASID API */
 enum {
     ASID_AVAILABLE = 0,
index 97a8837c21b9c4cf200f9ac38390523134b38844..b9abe0cd1a14eff7a10bf9bf8b37ccffd23a49c5 100644 (file)
@@ -457,7 +457,8 @@ struct arch_svm_struct {
     u64                 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
     int                 injecting_event;
     int                 saved_irq_vector;
-    u32                 core;        /* cpu of last vmexit */
+    u32                 launch_core;
+    u32                 asid_core;
     
     unsigned long       flags;      /* VMCB flags */
     unsigned long       cpu_shadow_cr0; /* copy of guest read shadow CR0 */